#include <stddef.h>
#include "LinkerTab.h"

void TLinkerUniverTabItem::MoveFrom(TLinkerUniverTabItem *p)
{
}

TLinkerUniverTabItem * TLinkerUniverTabItem::GetOffsetItem(size_t index)
{
    return & this[index]; 
}

TLinkerUniverTabItem::~TLinkerUniverTabItem()
{
}

TLinkerUniverTab::TLinkerUniverTab(size_t _group_base)
{
    group_base = _group_base;
    alloc_total = 0;
    elem_total = 0;
    head = NULL;
    rear = NULL;
}

TLinkerUniverTab::~TLinkerUniverTab()           
{
    size_t i;
    TLinkerUniverTabItemGroup * pgrp, * p;

    pgrp = head;
    while (pgrp)
    {
        p = pgrp->next;
        if (pgrp->groupdata)
            delete[] pgrp->groupdata;
        delete pgrp;
        pgrp = p;
    }

    alloc_total = 0;
    elem_total = 0;
    head = NULL;
    rear = NULL;
}

void TLinkerUniverTab::IncreaseGroupAlloc()
{
    TLinkerUniverTabItemGroup * grp;
    alloc_total += group_base;

    grp = new TLinkerUniverTabItemGroup;
    grp->groupdata = AllocGroupData(group_base);
    if (head == NULL)
    {
        grp->next = NULL;
        grp->prev = NULL;
        head = grp;
        rear = grp;
    }
    else
    {
        rear->next = grp;
        grp->next = NULL;
        grp->prev = rear;
        rear = grp;
    }
}

size_t TLinkerUniverTab::MoveElemInto(TLinkerUniverTabItem & elem)
{
    return MoveElemInto(&elem);
}

size_t TLinkerUniverTab::MoveElemInto(TLinkerUniverTabItem * pelem)
{
    size_t position;
    size_t cur_group;
    size_t i;
    TLinkerUniverTabItemGroup * pgrp;
    TLinkerUniverTabItem * p;

    if (elem_total >= alloc_total)
    {
        IncreaseGroupAlloc();
    }

    cur_group = elem_total / group_base;
    position = elem_total % group_base;

    pgrp = head;
    for (i = 0; i < cur_group; i++)
    {
        pgrp = pgrp->next;
    }

    p = pgrp->groupdata->GetOffsetItem(position);
    p->MoveFrom(pelem);

    elem_total ++;
    return (elem_total - 1);
}

TLinkerUniverTabItem* TLinkerUniverTab::AllocGroupData(size_t count)
{
    return new TLinkerUniverTabItem[count];
}

TLinkerUniverTabItem* TLinkerUniverTab::GetItem(size_t index)
{
    size_t grp_idx, get_idx;
    size_t i;
    TLinkerUniverTabItemGroup * pgrp;

    if (index >= elem_total)
        return NULL;
    grp_idx = index / group_base;
    get_idx = index % group_base;

    pgrp = head;
    for (i = 0; i < grp_idx; i++)
    {
        pgrp = pgrp->next;
    }

    return pgrp->groupdata->GetOffsetItem(get_idx);
}

size_t TLinkerUniverTab::GetTotalCount(void)
{
    return elem_total;
}





